﻿using System;
using System.IO;
using System.Collections.Generic;

using SBPweb.PhotoGallery.Common;

namespace SBPweb.PhotoGallery.Client.Logic
{

    public class FetchableSlide : Slide
    {

        #region Private fields

        private DownloadManager downloadManager = new DownloadManager();
        private Stream thumbnail = null;
        private Stream image = null;
        private Dictionary<string, object> context = new Dictionary<string, object>();
        private DownloadItem diImage;
        private DownloadItem diThumb;
        private bool isImageFetched;
        private bool isThumbFetched;

        #endregion

        #region Constructor logic

        public FetchableSlide(string imageUrl, string thumbUrl)
            :base(imageUrl, thumbUrl)
        {
        }

        public FetchableSlide(Uri imageUrl, Uri thumbUrl)
            : base(imageUrl, thumbUrl)
        {
        }

        public FetchableSlide(string imageUrl, string thumbUrl, string caption)
            : base(imageUrl, thumbUrl, caption)
        {
        }

        public FetchableSlide(Uri imageUrl, Uri thumbUrl, string caption)
            : base(imageUrl, thumbUrl, caption)
        {
        }

        public FetchableSlide(
            Uri imageUrl,
            Uri thumbUrl,
            string caption,
            int? duration,
            int? endDelay,
            int? animationBegin,
            int? animationEnd,
            double? centerX,
            double? centerY,
            double? scale,
            double? rotateAngle,
            bool? borderVisible,
            string borderColor,
            int? borderWidth,
            int? borderRadius)
            : base(imageUrl, thumbUrl, caption, duration, endDelay, animationBegin, animationEnd, centerX, centerY, scale, rotateAngle, borderVisible, borderColor, borderWidth, borderRadius)
        {
        }

        #endregion

        #region Property accessors

        public Stream Image
        {
            get
            {
                return image;
            }
        }

        public Stream Thumbnail
        {
            get
            {
                return thumbnail;
            }
        }

        public Dictionary<string, object> Context
        {
            get
            {
                return context;
            }
        }

        #endregion

        #region Events

        public event EventHandler<SlideFetchProgressEventArgs> ImageFetching;

        public event EventHandler<SlideFetchEventArgs> ImageFetched;

        public event EventHandler<SlideFetchErrorEventArgs> ImageFetchFailed;

        public event EventHandler<SlideFetchEventArgs> ImageFetchCancelled;

        public event EventHandler<SlideFetchProgressEventArgs> ThumbnailFetching;

        public event EventHandler<SlideFetchEventArgs> ThumbnailFetched;

        public event EventHandler<SlideFetchErrorEventArgs> ThumbnailFetchFailed;

        public event EventHandler<SlideFetchEventArgs> ThumbnailFetchCancelled;

        #endregion

        #region Methods

        private DownloadItem ProcessDownloadItem(Uri uri)
        {
            DownloadItem ret;
            if (context.ContainsKey("BaseUri"))
            {
                ret = new DownloadItem(new Uri(context["BaseUri"].ToString()), uri);
            }
            else
            {
                ret = new DownloadItem(uri);
            }
            return ret;
        }

        public void FetchImage()
        {
            if (isImageFetched)
            {
                if (ImageFetched != null)
                {
                    ImageFetched(this, new SlideFetchEventArgs(this));
                }
                return;
            }

            diImage = ProcessDownloadItem(this.ImageUri);
            diImage.DownloadStarted += new EventHandler<DownloadEventArgs>(diImage_DownloadStarted);
            diImage.DownloadCompleted += new EventHandler<DownloadStreamEventArgs>(diImage_DownloadCompleted);
            diImage.DownloadError += new EventHandler<DownloadErrorEventArgs>(diImage_DownloadError);
            diImage.DownloadCancelled += new EventHandler<DownloadEventArgs>(diImage_DownloadCancelled);
            diImage.DownloadProgressChanged += new EventHandler<DownloadProgressEventArgs>(diImage_DownloadProgressChanged);
            downloadManager.DownloadAsync(diImage);
        }

        public void FetchThumbnail()
        {
            if (isThumbFetched)
            {
                if (ThumbnailFetched != null)
                {
                    ThumbnailFetched(this, new SlideFetchEventArgs(this));
                }
                return;
            }

            diThumb = ProcessDownloadItem(this.ThumbnailUri);
            diThumb.DownloadStarted += new EventHandler<DownloadEventArgs>(diThumb_DownloadStarted);
            diThumb.DownloadCompleted += new EventHandler<DownloadStreamEventArgs>(diThumb_DownloadCompleted);
            diThumb.DownloadError += new EventHandler<DownloadErrorEventArgs>(diThumb_DownloadError);
            diThumb.DownloadCancelled += new EventHandler<DownloadEventArgs>(diThumb_DownloadCancelled);
            diThumb.DownloadProgressChanged += new EventHandler<DownloadProgressEventArgs>(diThumb_DownloadProgressChanged);
            downloadManager.DownloadAsync(diThumb);
        }

        #region Event handlers

        #region Image

        private void diImage_DownloadStarted(object sender, DownloadEventArgs e)
        {
            if (ImageFetching != null)
            {
                ImageFetching(this, new SlideFetchProgressEventArgs(this, new DownloadProgressEventArgs(e.Item)));
            }
        }

        private void diImage_DownloadCompleted(object sender, DownloadStreamEventArgs e)
        {
            image = e.Stream;
            isImageFetched = true;
            if (ImageFetched != null)
            {
                ImageFetched(sender, new SlideFetchEventArgs(this));
            }
        }

        private void diImage_DownloadError(object sender, DownloadErrorEventArgs e)
        {
            if (ImageFetchFailed != null)
            {
                ImageFetchFailed(sender, new SlideFetchErrorEventArgs(this, e));
            }
            else
            {
                throw e.Error;
            }
        }

        private void diImage_DownloadCancelled(object sender, DownloadEventArgs e)
        {
            if (ImageFetchCancelled != null)
            {
                ImageFetchCancelled(sender, new SlideFetchEventArgs(this));
            }
        }
        
        private void diImage_DownloadProgressChanged(object sender, DownloadProgressEventArgs e)
        {
            if (ImageFetching != null)
            {
                ImageFetching(sender, new SlideFetchProgressEventArgs(this, e));
            }
        }

        #endregion

        #region Thumnail

        private void diThumb_DownloadStarted(object sender, DownloadEventArgs e)
        {
            if (ThumbnailFetching != null)
            {
                ThumbnailFetching(this, new SlideFetchProgressEventArgs(this, new DownloadProgressEventArgs(e.Item)));
            }
        }

        private void diThumb_DownloadCompleted(object sender, DownloadStreamEventArgs e)
        {
            thumbnail = e.Stream;
            isThumbFetched = true;
            if (ThumbnailFetched != null)
            {
                ThumbnailFetched(sender, new SlideFetchEventArgs(this));
            }
        }

        private void diThumb_DownloadError(object sender, DownloadErrorEventArgs e)
        {
            if (ThumbnailFetchFailed != null)
            {
                ThumbnailFetchFailed(sender, new SlideFetchErrorEventArgs(this, e));
            }
            else
            {
                throw e.Error;
            }
        }

        private void diThumb_DownloadCancelled(object sender, DownloadEventArgs e)
        {
            if (ThumbnailFetchCancelled != null)
            {
                ThumbnailFetchCancelled(sender, new SlideFetchEventArgs(this));
            }
        }

        private void diThumb_DownloadProgressChanged(object sender, DownloadProgressEventArgs e)
        {
            if (ThumbnailFetching != null)
            {
                ThumbnailFetching(sender, new SlideFetchProgressEventArgs(this, e));
            }
        }

        #endregion

        #endregion

        #endregion

    }

}